#include "unicode_gbk.h"
#include "sys_init.h"
#include "string.h"
#include "utf8_to_gbk.h"

int enc_get_utf8_size(const unsigned char pInput);
unsigned short search_code_tab(unsigned short unicode);
int utf8_to_unicode(char* pOutput, const char *pInput);

/*******************************************************************************
* @brief  utf8 to unicode
* \param[in] pOut : pointer to resault
* \param[in] pInput : pointer to src data
* \retval: none
*******************************************************************************/
int utf8_to_unicode(char* pOutput, const char *pInput)
{
	char b1, b2, b3, b4, b5, b6;
	int len = enc_get_utf8_size(*pInput);

	switch (len)
	{
		case 0:
			*pOutput = *pInput;
			len += 1;
			break;
		case 2:
			b1 = *pInput;
			b2 = *(pInput + 1);
			if ((b2 & 0xC0) != 0x80)
				return 0;
			*pOutput = (b1 << 6) + (b2 & 0x3F);
			*(pOutput + 1) = (b1 >> 2) & 0x07;
			break;
		case 3:
			b1 = *pInput;
			b2 = *(pInput + 1);
			b3 = *(pInput + 2);
			if (((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80))
				return 0;
			*pOutput = ((b2 & 0x03) << 6) + (b3 & 0x3F);
			*(pOutput + 1) = ((b1 & 0x0F) << 4) | ((b2 >> 2) & 0x0F);
			break;
		case 4:
			b1 = *pInput;
			b2 = *(pInput + 1);
			b3 = *(pInput + 2);
			b4 = *(pInput + 3);
			if (((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80)
				|| ((b4 & 0xC0) != 0x80))
				return 0;
			*pOutput = (b3 << 6) + (b4 & 0x3F);
			*(pOutput + 1) = (b2 << 4) + ((b3 >> 2) & 0x0F);
			*(pOutput + 2) = ((b1 << 2) & 0x1C) + ((b2 >> 4) & 0x03);
			break;
		case 5:
			b1 = *pInput;
			b2 = *(pInput + 1);
			b3 = *(pInput + 2);
			b4 = *(pInput + 3);
			b5 = *(pInput + 4);
			if (((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80)
				|| ((b4 & 0xC0) != 0x80) || ((b5 & 0xC0) != 0x80))
				return 0;
			*pOutput = (b4 << 6) + (b5 & 0x3F);
			*(pOutput + 1) = (b3 << 4) + ((b4 >> 2) & 0x0F);
			*(pOutput + 2) = (b2 << 2) + ((b3 >> 4) & 0x03);
			*(pOutput + 3) = (b1 << 6);
			break;
		case 6:
			b1 = *pInput;
			b2 = *(pInput + 1);
			b3 = *(pInput + 2);
			b4 = *(pInput + 3);
			b5 = *(pInput + 4);
			b6 = *(pInput + 5);
			if (((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80)
				|| ((b4 & 0xC0) != 0x80) || ((b5 & 0xC0) != 0x80)
				|| ((b6 & 0xC0) != 0x80))
				return 0;
			*pOutput = (b5 << 6) + (b6 & 0x3F);
			*(pOutput + 1) = (b5 << 4) + ((b6 >> 2) & 0x0F);
			*(pOutput + 2) = (b3 << 2) + ((b4 >> 4) & 0x03);
			*(pOutput + 3) = ((b1 << 6) & 0x40) + (b2 & 0x3F);
			break;
		default:
			return 0;
	}
	return len;
}

/*******************************************************************************
* @brief  get a utf8 char length
* \param[in] pInput : pointer to src data
* \retval: none
*******************************************************************************/
int enc_get_utf8_size(const unsigned char pInput)
{
	int num = 0, temp = 0x80;

	while (temp&pInput)
	{
		num++;
		temp = (temp >> 1);
	}

	return num;
}

/*******************************************************************************
* @brief  unicode to gbk
* \param[in] pOut : pointer to resault
* \param[in] pInput : pointer to src data
* \retval: none
*******************************************************************************/
void unicode_to_gbk(char*pOut, const char *pInput)
{
	dword_tt tmp, gbk_tmp;

	memcpy(&tmp, pInput, 2);

	gbk_tmp.uval = encode_uni2gbk(tmp.uval, 936);
	
	//调整为小端，大地址存高位，小地址存低位
	*pOut++ = gbk_tmp.v[1];
	*pOut = gbk_tmp.v[0];
}

/*******************************************************************************
* @brief  utf8 to gbk
* \param[in] pOut : pointer to resault
* \param[in] pInput : pointer to src data
* \retval: none
*******************************************************************************/
int  utf8_to_gbk(char*pOut, const char *pInput, int pLen)
{
	int res, i = 0, j = 0;
	char tempbuf[8];

	while (i < pLen)
	{
		memset(tempbuf, 0, sizeof(tempbuf));
		
		res = utf8_to_unicode(tempbuf, pInput + i);

		if (res <= 0)
		{
			return 0;
		}
		else if (res == 1)
		{
			*(pOut + j) = *(pInput + i);
			j += 1;
		}
		else{
			unicode_to_gbk(pOut + j, tempbuf);
			j += 2;
		}

		// add at 20210616
		if (!*(pInput + i))
			break;

		i += res;
	}

	return 1;
}
